﻿#include "MaterialGraphNodeViewModel.h"

#include "MaterialGraph/MaterialGraphViewModel.h"

#include "Framework/Editor.h"

#include "MaterialGraph/Pin/MaterialGraphPinViewModel.h"
#include "MaterialGraph/Pin/MaterialGraphPinModel.h"


void RMaterialGraphNodeViewModel::BindModel(TSharedObjectPtr<RMaterialGraphNodeModel> InModel, TSharedObjectPtr<RMaterialGraphViewModel> InGraph)
{
    BaseNodeModel = InModel;
    GraphViewModel = InGraph;

    for(int64_t i = 0; i < BaseNodeModel->GetOutputNum(); i++)
    {
        CClass * ViewModelClass =  REditor::Get()->GetViewModelClass(BaseNodeModel->GetOutput(i)->GetClass());
        auto OutputViewModel = NewObject<RMaterialGraphPinViewModel>(ViewModelClass, this);
        OutputViewModel->BindModel(BaseNodeModel->GetOutput(i), this);
        OutputViewModels.Add(OutputViewModel);
    }

    for(int64_t i = 0; i < BaseNodeModel->GetInputNum(); i++)
    {
        CClass * ViewModelClass =  REditor::Get()->GetViewModelClass(BaseNodeModel->GetInput(i)->GetClass());
        auto InputViewModel = NewObject<RMaterialGraphPinViewModel>(ViewModelClass, this);
        InputViewModel->BindModel(BaseNodeModel->GetInput(i), this);
        InputViewModels.Add(InputViewModel);
    }

}

TSharedObjectPtr<RMaterialGraphViewModel> RMaterialGraphNodeViewModel::GetGraphViewModel() const
{
    return GraphViewModel;
}

float RMaterialGraphNodeViewModel::GetScale() const
{
    return GraphViewModel->GraphScale;
}

SVec2 RMaterialGraphNodeViewModel::GetGraphOffset() const
{
    return GraphViewModel->GetGraphOffset();
}

float RMaterialGraphNodeViewModel::GetNodeX() const
{
    return BaseNodeModel->Position.X;
}

float RMaterialGraphNodeViewModel::GetNodeY() const
{
    return BaseNodeModel->Position.Y;
}

void RMaterialGraphNodeViewModel::SetNodePosition(const SVec2 &InPos)
{

    auto MoveNodeOperation = NewObject<RMaterialMoveNodeOperation>();
    MoveNodeOperation->Node = BaseNodeModel;
    MoveNodeOperation->OldPosition = BaseNodeModel->Position;
    MoveNodeOperation->NewPosition = InPos;

    GraphViewModel->RedoOperation(MoveNodeOperation);
    GraphViewModel->AddOperation(MoveNodeOperation);
}

float RMaterialGraphNodeViewModel::GetNodeWidgetSpaceX() const
{
    float Offset= GetGraphOffset().X+ GetNodeX();
    return Offset* GetScale();
}

float RMaterialGraphNodeViewModel::GetNodeWidgetSpaceY() const
{
    float Offset= GetGraphOffset().Y+ GetNodeY();
    return Offset* GetScale();
}

float RMaterialGraphNodeViewModel::GetLineY(int64_t InLineIndex) const
{
    return (LineHeight+LineVerticalPadding) * InLineIndex;
}

bool RMaterialGraphNodeViewModel::IsSelected() const
{
    return GraphViewModel->IsNodeSelected(this);
}

float RMaterialGraphNodeViewModel::GetNodeHeight() const
{
    int64_t LineNum = GetLineNum();
    assert(LineNum > 0);
    return
        LineNum* LineHeight
        + (LineNum-1) * LineVerticalPadding
        + LineVerticalPadding * 0.5f //bottom padding
        ;
}

SColor RMaterialGraphNodeViewModel::GetOutputNodeTitleBackgroundColor() const
{
    if(GraphViewModel->IsCurrentOutputNode(this))
    {
        static SColor TitleColor=SColor::FromHexRGB(0x83314A);
        return TitleColor;
    }
    else
    {
        //完全透明
        return SColor(0.f, 0.f, 0.f, 0.0f);
    
    }
}

int64_t RMaterialGraphNodeViewModel::GetInputNum() const
{
    return InputViewModels.Num();
}

TSharedObjectPtr<RMaterialGraphPinViewModel> RMaterialGraphNodeViewModel::GetInput(int64_t Index) const
{
    return InputViewModels[Index];
}

float RMaterialGraphNodeViewModel::GetInputDefaultX(int64_t Index) const
{
    return InputViewModels[Index]->GetDefaultX();
}

void RMaterialGraphNodeViewModel::SetInputDefaultX(int64_t Index, float InValue)
{
    InputViewModels[Index]->SetDefaultX(InValue);
}

float RMaterialGraphNodeViewModel::GetInputDefaultY(int64_t Index) const
{
    return InputViewModels[Index]->GetDefaultY();
}

void RMaterialGraphNodeViewModel::SetInputDefaultY(int64_t Index, float InValue)
{
    InputViewModels[Index]->SetDefaultY(InValue);
}

float RMaterialGraphNodeViewModel::GetInputDefaultZ(int64_t Index) const
{
    return InputViewModels[Index]->GetDefaultZ();
}

void RMaterialGraphNodeViewModel::SetInputDefaultZ(int64_t Index, float InValue)
{
    InputViewModels[Index]->SetDefaultZ(InValue);
}

int64_t RMaterialGraphNodeViewModel::GetOutputNum() const
{
    return OutputViewModels.Num();
}

TSharedObjectPtr<RMaterialGraphPinViewModel> RMaterialGraphNodeViewModel::GetOutput(int64_t Index) const
{
    return OutputViewModels[Index];
}

void RMaterialGraphNodeViewModel::OnPinDragStarted(TSharedObjectPtr<RMaterialGraphPinViewModel> InPin)
{
    GraphViewModel->OnPinDragStarted(InPin);
}

void RMaterialGraphNodeViewModel::OnPinDragEnded(TSharedObjectPtr<RMaterialGraphPinViewModel> InPin)
{
    GraphViewModel->OnPinDragEnded(InPin);
}

void RMaterialGraphNodeViewModel::SelectThisNode()
{
    GraphViewModel->SelectNode(this);
}

TSharedObjectPtr<RMaterialGraphNodeModel> RMaterialGraphNodeViewModel::GetBaseNodeModel() const
{
    return BaseNodeModel;
}

void RMaterialMoveNodeOperation::Undo(TSharedObjectPtr<RMaterialGraphModel> InGraph)
{
    Node->Position = OldPosition;
}

void RMaterialMoveNodeOperation::Redo(TSharedObjectPtr<RMaterialGraphModel> InGraph)
{
    Node->Position = NewPosition;
}

bool RMaterialMoveNodeOperation::CombineTo(TSharedObjectPtr<RMaterialEditOperation> InFormerOperation)
{
    if(!InFormerOperation->IsA<RMaterialMoveNodeOperation>())
    {
        return false;
    }

    RMaterialMoveNodeOperationPtr FormerMoveNodeOperation = InFormerOperation;

    if(FormerMoveNodeOperation->Node != Node)
    {
        return false;
    }

    FormerMoveNodeOperation->NewPosition = NewPosition;

    return true;
}
